package yxy.cherry.battle;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import yxy.apple.util.RandomUtility;
import yxy.cherry.battle.module.Position;
import yxy.cherry.battle.module.actor.*;
import yxy.cherry.battle.module.affix.AffixContext;
import yxy.cherry.battle.module.record.Record;
import yxy.cherry.battle.module.record.result.BattleResult;
import yxy.cherry.battle.module.record.result.StatisticFighter;
import yxy.cherry.battle.module.record.stream.RecordStream_END;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;

import static yxy.cherry.battle.module.affix.Affix.VALUE_比率分母;

public class Battle {

    private static Logger logger = LoggerFactory.getLogger(Battle.class);


    Record 记录 = new Record();

    BattleContext context;// 上下文

    public Record get记录() {
        return 记录;
    }

    public void battle(Team team_a, Team team_b) {
        battle(team_a, team_b, -1);
    }

    public void battle(Team team_a, Team team_b, int roundLimit) {


        context = new BattleContext(roundLimit);

        Actor actor = initActors(team_a, team_b);

        while (team_a.is有活口() && team_b.is有活口() && !getContext().roundLimit(getContext().getRound())) {
            actor.action();
            actor = actor.getNextActor();
        }
        get记录().stream(new RecordStream_END()).record();
        Battle.battleLogger(1, "战斗结束");


        // 赛后统计
        for (Fighter fighter : team_a.getFighters()) {
            StatisticFighter statisticFighter = get记录().get统计().getFighter(fighter.getFighterPosition());
            statisticFighter.setHpu(fighter.get生命());
            statisticFighter.setHpc(fighter.get血量());
            statisticFighter.setAng(fighter.getAnger());
        }
        if (team_a.get神兵() != null) {
            StatisticFighter statisticFighter = get记录().get统计().getFighter(team_a.get神兵().getFighterPosition());
            statisticFighter.setAng(team_a.get神兵().getAnger());
        }
        for (Fighter fighter : team_b.getFighters()) {
            StatisticFighter statisticFighter = get记录().get统计().getFighter(fighter.getFighterPosition());
            statisticFighter.setHpu(fighter.get生命());
            statisticFighter.setHpc(fighter.get血量());
            statisticFighter.setAng(fighter.getAnger());
        }
        if (team_b.get神兵() != null) {
            StatisticFighter statisticFighter = get记录().get统计().getFighter(team_b.get神兵().getFighterPosition());
            statisticFighter.setAng(team_b.get神兵().getAnger());
        }

        boolean teamA活着 = team_a.is有活口();
        boolean teamB活着 = team_b.is有活口();
        if (teamA活着 && !teamB活着) {
            Double per = countHP(team_a) / countLife(team_a);
            BattleResult result = genBattleResult(per, BattleResult.LEFT_WIN);//更详细的战斗结果  险胜 险败等等
            get记录().setDetailResult(result);
            get记录().setResult(BattleResult.LEFT_WIN);
        } else if (!teamA活着 && teamB活着) {
            Double per = countHP(team_b) / countLife(team_b);
            BattleResult result = genBattleResult(per, BattleResult.RIGHT_WIN);//更详细的战斗结果  险胜 险败等等
            get记录().setDetailResult(result);
            get记录().setResult(BattleResult.RIGHT_WIN);
        } else {
            get记录().setResult(BattleResult.DRAW);
        }

        if (!team_a.is有活口()) {
            Record.stdout("Team_A 全灭");
        }
        if (!team_b.is有活口()) {
            Record.stdout("Team_B 全灭");
        }
        Record.stdout(get记录().info());
        Record.stdout(get记录().streamInfo());
    }

    /**
     * 计算所有人的生命值
     *
     * @param team
     * @return
     */
    private double countLife(Team team) {
        Double life = Double.valueOf(0);
        for (Fighter fighter : team.getFighters()) {
            life = life + fighter.get生命();
        }
        return life;
    }

    /**
     * 计算活人血量
     *
     * @param team
     * @return
     */
    private Double countHP(Team team) {
        Double hp = Double.valueOf(0);
        for (Fighter fighter : team.get活人()) {
            if (fighter.is活着()) {
                hp = hp + fighter.get血量();
            }
        }
        return hp;
    }


    /**
     * 生成战斗评价
     *
     * @param per
     * @param battleResult
     * @return
     */
    private BattleResult genBattleResult(Double per, BattleResult battleResult) {
        double p = per * VALUE_比率分母;
        double p0 = (Double.valueOf(3) * VALUE_比率分母 / Double.valueOf(4));
        if (p >= p0) {
            if (battleResult == BattleResult.LEFT_WIN) {
                return BattleResult.LEFT_WIN_DEFEAT;
            } else {
                return BattleResult.RIGHT_WIN_DEFEAT;
            }
        }

        double p1 = (Double.valueOf(2) * VALUE_比率分母 / Double.valueOf(4));
        if (p >= p1) {
            if (battleResult == BattleResult.LEFT_WIN) {
                return BattleResult.LEFT_WIN_WHUP;
            } else {
                return BattleResult.RIGHT_WIN_WHUP;
            }
        }

        double p2 = (Double.valueOf(1) * VALUE_比率分母 / Double.valueOf(4));
        if (p >= p2) {
            if (battleResult == BattleResult.LEFT_WIN) {
                return BattleResult.LEFT_WIN_WIN;
            } else {
                return BattleResult.RIGHT_WIN_WIN;
            }
        }

        if (p > 0) {
            if (battleResult == BattleResult.LEFT_WIN) {
                return BattleResult.LEFT_WIN_NARROW;
            } else {
                return BattleResult.RIGHT_WIN_NARROW;
            }
        }

        return BattleResult.DRAW;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////

    /**
     * 初始化所有行动单元
     * 武将按速度进行排序出手队列
     * 神器出手排在每个武将前面
     * -
     */
    private Actor initActors(Team team_a, Team team_b) {
        LinkedList<Actor> sequence = get出手队列(team_a, team_b);
        //给神兽添加上下文
        initPokemom(team_a, team_b);
        Actor 初始化 = new Actor_初始化();
        初始化.setNextActor(new Actor_初始轮())//
                .setNextActor(new Actor_下一轮())//
                .setNextActor(new Actor_神兽())
                .setNextActor(sequence.getFirst());
        sequence.getLast()//
                .setNextActor(new Actor_下一轮())//
                .setNextActor(sequence.getFirst());

        initContext(初始化, team_a, team_b);
        initRecord(初始化);
        return 初始化;
    }

    /**
     * 给神兽添加上下文
     */
    private void  initPokemom(Team team_a, Team team_b){
        yxy.cherry.battle.Pokemon pokemonsA = team_a.getPokemon();
        if(pokemonsA != null) {
            pokemonsA.setContext(context);
            pokemonsA.setRecord(记录);
        }
        yxy.cherry.battle.Pokemon pokemonsB = team_b.getPokemon();
        if(pokemonsB != null){
            pokemonsB.setContext(context);
            pokemonsB.setRecord(记录);
        }
    }

    private void initContext(Actor 初始化, Team team_a, Team team_b) {
        context.setTeam(team_a, team_b);
        context.setAffixContext(new AffixContext());
        for (Fighter fighter : team_a.getFighters()) {
            fighter.setFighterPosition(true);
        }
        for (Fighter fighter : team_b.getFighters()) {
            fighter.setFighterPosition(false);
        }
        Actor temp = 初始化;
        while (temp.getContext() == null) {//给每个Actor 加上下文属性
            temp.setContext(context);
            temp = temp.getNextActor();
        }
    }

    private void initRecord(Actor 初始化) {
        Actor temp = 初始化;
        while (temp.getRecord() == null) {
            temp.setRecord(记录);
            temp = temp.getNextActor();
        }
    }

    /**
     * 所有英雄的出手顺序
     */
    private LinkedList<Actor> get出手队列(Team team_a, Team team_b) {
        ArrayList<Fighter> fighters = new ArrayList<>(team_a.getFighters());
        fighters.sort((t1, t2) -> (int) (t2.get速度() - t1.get速度()));//降序排列
        ArrayList<Fighter> fighters2 = new ArrayList<>(team_b.getFighters());
        fighters2.sort((t1, t2) -> (int) (t2.get速度() - t1.get速度()));
        boolean isPriorityA = is队伍A优先(team_a, team_b);
        LinkedList<Actor> sequence = new LinkedList<>();

        while ((fighters.size() + fighters2.size()) > 0) {
            //各取双方排名前一位的选手出来比较
            Fighter fighterA0 = null;
            if (fighters.size() > 0) {
                fighterA0 = fighters.get(0);
            }
            Fighter fighterB0 = null;
            if (fighters2.size() > 0) {
                fighterB0 = fighters2.get(0);
            }

            if (fighterA0 == null) {
                if (fighterB0 == null) {
                    break;
                } else {
                    pushFighter(sequence, team_b, fighterB0, fighters2);
                }
            } else {
                if (fighterB0 == null) {
                    pushFighter(sequence, team_a, fighterA0, fighters);
                } else {
                    if (fighterA0.get速度() > fighterB0.get速度()) {
                        pushFighter(sequence, team_a, fighterA0, fighters);
                    } else if (fighterA0.get速度() < fighterB0.get速度()) {
                        pushFighter(sequence, team_b, fighterB0, fighters2);
                    } else {//速度相等，则依据战力和随机判定优先
                        if (isPriorityA) {
                            pushFighter(sequence, team_a, fighterA0, fighters);
                        } else {
                            pushFighter(sequence, team_b, fighterB0, fighters2);
                        }
                    }
                }
            }
        }
        // 出手顺序：前排 上 中 下 后排 上 中 下
//		pushFighterInSeq(sequence, team_优先, Position.FU);
//		pushFighterInSeq(sequence, team_随后, Position.FU);
//		pushFighterInSeq(sequence, team_随后, Position.FM);
//		pushFighterInSeq(sequence, team_优先, Position.FM);
//		pushFighterInSeq(sequence, team_优先, Position.FD);
//		pushFighterInSeq(sequence, team_随后, Position.FD);
//		pushFighterInSeq(sequence, team_随后, Position.BU);
//		pushFighterInSeq(sequence, team_优先, Position.BU);
//		pushFighterInSeq(sequence, team_优先, Position.BM);
//		pushFighterInSeq(sequence, team_随后, Position.BM);
//		pushFighterInSeq(sequence, team_随后, Position.BD);
//		pushFighterInSeq(sequence, team_优先, Position.BD);

        // 出手顺序：先手前上 后手前上 先手前中 后手前中 ...
//		pushFighterInSeq(sequence, team_优先, Position.FU);
//		pushFighterInSeq(sequence, team_随后, Position.FU);
//		pushFighterInSeq(sequence, team_优先, Position.FM);
//		pushFighterInSeq(sequence, team_随后, Position.FM);
//		pushFighterInSeq(sequence, team_优先, Position.FD);
//		pushFighterInSeq(sequence, team_随后, Position.FD);
//		pushFighterInSeq(sequence, team_优先, Position.BU);
//		pushFighterInSeq(sequence, team_随后, Position.BU);
//		pushFighterInSeq(sequence, team_优先, Position.BM);
//		pushFighterInSeq(sequence, team_随后, Position.BM);
//		pushFighterInSeq(sequence, team_优先, Position.BD);
//		pushFighterInSeq(sequence, team_随后, Position.BD);
        // TODO 处理神兵
        for (int i = 1; i < sequence.size(); i++) {
            sequence.get(i - 1).setNextActor(sequence.get(i));
        }
        return sequence;
    }

    /**
     * 处理队内逻辑，和排名第二的选手比较速度
     *
     * @param sequence
     * @param team
     * @param fighter
     * @param fighters
     */
    private void pushFighter(LinkedList<Actor> sequence, Team team, Fighter fighter, ArrayList<Fighter> fighters) {
        if (fighters.size() > 1) {
            ArrayList<Integer> list = new ArrayList<>();
            list.add(0);
            for (int i = 1; i < fighters.size(); i++) {
                Fighter fighterT = fighters.get(i);
                if (fighterT.get速度() == fighter.get速度()) {
                    list.add(i);
                }
            }
            Collections.shuffle(list);
            int index = list.get(0);
            Collections.swap(fighters, index, 0);
        }
        pushFighterInSeq(sequence, team, fighters.get(0));
        fighters.remove(0);
    }

    private void pushFighterInSeq(LinkedList<Actor> sequence, Team team, Fighter fighter) {
        if (fighter == null) {
            return;
        }
        NiuBee niubee = team.get神兵();
        if (niubee != null) {
            sequence.add(new Actor_神兵(niubee));// 神兵
        }
        niubee = team.getTeam对手().get神兵();
        if (niubee != null) {
            sequence.add(new Actor_神兵(niubee));// 神兵
        }
        sequence.add(fighter);
    }

    private void pushFighterInSeq(LinkedList<Actor> sequence, Team team, Position position) {
        Fighter fighter = team.getFighterByPosition(position);
        if (fighter == null) {
            return;
        }
        NiuBee niubee = team.get神兵();
        if (niubee != null) {
            sequence.add(new Actor_神兵(niubee));// 神兵
        }
        niubee = team.getTeam对手().get神兵();
        if (niubee != null) {
            sequence.add(new Actor_神兵(niubee));// 神兵
        }
        sequence.add(fighter);
    }
    /////////////////////////////////////////////////////////////////////////////////////////

    /**
     * 根据战力或其他规则 确定先出手的队伍
     */
    private boolean is队伍A优先(Team team_a, Team team_b) {
        double powerA = team_a.getBattlePower();
        double powerB = team_b.getBattlePower();
        // 战力优先，战力一致则随机优先
        if (powerA == powerB) {
            return RandomUtility.nextInt(0, 2) < 1;
        }
        return powerA > powerB;
    }

    public BattleContext getContext() {
        return context;
    }


    static int logLevel = 0;


    public static void battleLogger(int level, String info) {
        String outInfo = "";
        if (level <= logLevel) {
            while (level > 0) {
                outInfo = outInfo + "    ";
                level--;
            }
            outInfo = outInfo + info;
            System.out.println(outInfo);
        }
//        logger.debug(outInfo);
    }

}
